home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / earcd / util / sys / msys_1_2.lha / Src / makelink.c < prev    next >
C/C++ Source or Header  |  1996-02-10  |  8KB  |  243 lines

  1. /*
  2. **    makelink.c - create filesystem links
  3. **    $VER: makelink.c 42.1 (10.2.96)
  4. **    Copyright © 1996 Michal Letowski
  5. **
  6. **    42.1 (10.2.96) - initial version
  7. */
  8.  
  9. #define __USE_SYSBASE
  10.  
  11. #include <exec/types.h>
  12. #include <exec/execbase.h>
  13. #include <exec/libraries.h>
  14. #include <dos/dos.h>
  15. #include <dos/dosextens.h>
  16. #include <dos/rdargs.h>
  17. #include <support/types.h>
  18. #include <support/dos.h>
  19.  
  20. #include <string.h>
  21.  
  22. #include <proto/exec.h>
  23. #include <proto/dos.h>
  24.  
  25. #include "makelink.rev.h"
  26.  
  27.  
  28. /*
  29. **    Constants
  30. */
  31. #define DOS_NAME            "dos.library"
  32. #define DOS_VERN            37L
  33.  
  34. #define TEMPLATE            "FROM/A,TO/A,HARD/S,SOFT/S,FORCE/S"
  35.  
  36. #define TEST_ERROR        -1L
  37. #define TEST_FILE            0L
  38. #define TEST_DIR            1L
  39.  
  40.  
  41. /*
  42. **    Private structures
  43. */
  44. struct Options
  45. {
  46.     STRPTR opt_From;                                                            /* FROM/A */
  47.     STRPTR opt_To;                                                                /* TO/A */
  48.     LBOOL  opt_Hard;                                                            /* HARD/S */
  49.     LBOOL  opt_Soft;                                                            /* SOFT/S */
  50.     LBOOL  opt_Force;                                                            /* FORCE/S */
  51. };    /* Options */
  52.  
  53.  
  54. /*
  55. **    Global data
  56. */
  57. STATIC CONST TEXT VersionString[]=
  58.     VERSION(PROG_NAME,PROG_VERSION,PROG_REVISION,PROG_DATE);
  59.  
  60.  
  61. /*
  62. **    Private functions prototypes
  63. */
  64. STATIC LONG TestLock(struct Options *opts, BPTR lock, struct Library *DOSBase);
  65.  
  66.  
  67. /*
  68. **    Public functions
  69. */
  70. /****** C/MakeLink **********************************************************
  71. *
  72. *   NAME
  73. *       MakeLink -- create filesystem links. (V42)
  74. *
  75. *   SYNOPSIS
  76. *       MakeLink Source Target [HARD] [SOFT] [FORCE]
  77. *
  78. *   TEMPLATE
  79. *       MakeLink "FROM/A,TO/A,HARD/S,SOFT/S,FORCE/S"
  80. *
  81. *   FUNCTION
  82. *       MakeLink creates links to other files or directories. A link is a
  83. *       directory entry that points to other file or directory. There are
  84. *       two kinds of links:
  85. *           hard links - this link points to an already existing file or
  86. *                        directory located on the same partition;
  87. *           soft links - such links may point to any objects (including
  88. *                        devices, volumes, and partitions) and as such are
  89. *                        more flexible.
  90. *       MakeLink creates a Source name link that points to Target. HARD
  91. *       options (default) indicates that it is a hard link. SOFT option
  92. *       indicates a soft link. You can't specify both HARD and SOFT. When
  93. *       creating hard links to directories FORCE option must be given.
  94. *       MakeLink detects circular (i.e. to parent directories) dependencies
  95. *       during creation of hard links and will not create such links.
  96. *
  97. *   INPUTS
  98. *       Source - name of symbolic link to create.
  99. *       Target - name of link target. In case of hard links must be an
  100. *                existing directory or file name.
  101. *       HARD   - indicates hard link (default).
  102. *       SOFT   - indicates soft link.
  103. *       FORCE  - this keyword must appears during creation of hard links to
  104. *                directories, ignored for soft links.
  105. *
  106. *   RESULT
  107. *       RETURN_FAIL  - if 'dos.library' couldn't be opened or command line
  108. *                      arguments couldn't be processed or both HARD and SOFT
  109. *                      options appeared on command line.
  110. *       RETURN_ERROR - circular dependency was detected (ERROR_OBJECT_LINKED),
  111. *                      link couldn't be created or some other error.
  112. *       RETURN_OK    - if a link was created.
  113. *
  114. *   EXAMPLE
  115. *       MakeLink SYS:Utilities/More C:PPMore
  116. *           ; Creates SYS:Utilities/More file that in reality is the C:PPMore.
  117. *       MakeLink DF0.link DF0: SOFT
  118. *           ; Creates DF0.link pseudo-directory which points to a disk in
  119. *           ; DF0: drive.
  120. *       MakeLink Work:Music/Lyrics Work:Docs/Lyrics FORCE
  121. *           ; Creates Work:Music/Lyrics directory which points to
  122. *           ; Work:Docs/Lyrics
  123. *
  124. *   NOTES
  125. *       Links (especially soft) are not fully supported in current AmigaDOS
  126. *       releases. This is why soft links - even pointing to files - will
  127. *       look like directories to most of the programs. Creating soft links
  128. *       to handlers (like SPEAK:) may yield very strange results.
  129. *       MakeLink is pure and can be made resident.
  130. *
  131. *   BUGS
  132. *       In FastFileSystem before version 40 when referencing a soft link it
  133. *       must be the last part of the path. There is also a bug regarding
  134. *       removing the target of the hard link (in FastFileSystem, too).
  135. *
  136. *   SEE ALSO
  137. *       dos.library/MakeLink().
  138. *
  139. *****************************************************************************
  140. *
  141. */
  142. LONG MakeLinkCom(VOID)
  143. {
  144.     struct ExecBase *SysBase=INITSYSBASE;
  145.     struct Library *DOSBase;
  146.  
  147.     struct Options Opts;
  148.     struct RDArgs *Args;
  149.     BPTR DstLock;
  150.     LONG LR,RC=RETURN_FAIL;
  151.     
  152.     /* Open DOS */
  153.     unless(DOSBase=OpenLibrary(DOS_NAME,DOS_VERN))
  154.         throw2(SetResult2(ERROR_INVALID_RESIDENT_LIBRARY),    NO_DOS);
  155.  
  156.     /* Read arguments */
  157.     clear(&Opts);                                                                    /* Clear out buffer */
  158.     unless(Args=ReadArgs(TEMPLATE,(LONG *)&Opts,NULL))
  159.         throw2(PrintFault(IoErr(),PROG_NAME),                                NO_ARGS);
  160.     if(Opts.opt_Hard && Opts.opt_Soft)                        /* Check options */
  161.         throw2(CauseIoErr(ERROR_TOO_MANY_ARGS,PROG_NAME),        BAD_ARGS);
  162.  
  163.     RC=RETURN_ERROR;                                                            /* Working a bit... */
  164.  
  165.     /* Do the job */
  166.     if(Opts.opt_Soft)                                                            /* Softlink */
  167.         if(MakeLink(Opts.opt_From,(LONG)Opts.opt_To,LINK_SOFT))
  168.             RC=RETURN_OK;
  169.         else
  170.             PrintFault(IoErr(),Opts.opt_From);
  171.     else                                                                                    /* Hardlink (by default!) */
  172.         if(DstLock=Lock(Opts.opt_To,SHARED_LOCK))        /* Try to lock destination */
  173.         {                                                                                        /* Locking successfull */
  174.             LR=TestLock(&Opts,DstLock,DOSBase);                /* Test for circular locks */
  175.             if(LR>0 && !Opts.opt_Force)
  176.                 PutStr("Links to directories require use of the FORCE keyword\n");
  177.             elif(LR>=0)
  178.                 if(MakeLink(Opts.opt_From,DstLock,LINK_HARD))
  179.                     RC=RETURN_OK;                                                    /* Link created - success */
  180.                 else                                                                        /* Creation unsuccessfull */
  181.                     PrintFault(IoErr(),Opts.opt_From);        /* Print error message */
  182.             UnLock(DstLock);                                                    /* Remove lock */
  183.         }
  184.         else                                                                                /* No lock on destination */
  185.             PrintFault(IoErr(),Opts.opt_To);                    /* Inform user */
  186.             
  187.     /* Exceptions */
  188.     catch(BAD_ARGS,    );
  189.     catch(NO_ARGS,    FreeArgs(Args));
  190.     catch(NO_DOS,        CloseLibrary(DOSBase));
  191.     return(RC);
  192. }    /* MakeLinkCom */
  193.  
  194.  
  195. /*
  196. **    Private functions
  197. */
  198. /* Returns -1 if error, 0 if file or 1 if directory */
  199. STATIC LONG TestLock(struct Options *opts, BPTR lock, struct Library *DOSBase)
  200. {
  201.     CHAR Buffer[MAX_PATH_LEN];
  202.  
  203.     struct FileInfoBlock *FIB;
  204.     BPTR L1,L2;
  205.     LONG RC=TEST_ERROR;                                                            /* To indicate circular link */
  206.  
  207.     if(FIB=AllocDosObject(DOS_FIB,NULL))                        /* Try to allocate FileInfoBlock */
  208.     {                                                                                                /* Allocation successfull */
  209.         if(Examine(lock,FIB))                                                    /* Try to examine lock */
  210.             if(FIB->fib_EntryType>=0)                                        /* Directory check */
  211.             {                                                                                        /* It's a directory */
  212.                 RC=TEST_DIR;                                                            /* Set result to 'dir' */
  213.                 strcpy(Buffer,opts->opt_From);                        /* Make a copy of path */
  214.                 *PathPart(Buffer)='\0';                                        /* NULL-terminate path */
  215.                 if(L1=Lock(Buffer,SHARED_LOCK))                        /* Try to lock FROM path */
  216.                     do
  217.                     {
  218.                         if(SameLock(L1,lock)==LOCK_SAME)            /* Compare lock */
  219.                         {                                                                            /* Lock is the same */
  220.                             RC=TEST_ERROR;                                            /* Mark loop detection */
  221.                             CauseIoErr(ERROR_OBJECT_LINKED,opts->opt_To);
  222.                             L2=NULL;                                                        /* To break loop */
  223.                         }
  224.                         else                                                                    /* Lock is different */
  225.                             L2=ParentDir(L1);                                        /* Go level up */
  226.                         UnLock(L1);                                                        /* Remove old lock */
  227.                         L1=L2;                                                                /* Make old lock a new one */
  228.                     } while(L1);                                                        /* While valid lock */
  229.                 else
  230.                     PrintFault(IoErr(),Buffer);                            /* Print error if impossible */
  231.             }
  232.             else                                                                                /* It's a file */
  233.                 RC=TEST_FILE;                                                            /* Set result to 'file' */
  234.         else                                                                                /* Could not examine */
  235.             PrintFault(IoErr(),opts->opt_To);                    /* Print error message */
  236.         FreeDosObject(DOS_FIB,FIB);                                    /* Free FileInfoBlock */
  237.     }
  238.     else                                                                                    /* Allocation unsuccessfull */
  239.         PrintFault(IoErr(),PROG_NAME);                            /* Print error message */
  240.  
  241.     return(RC);
  242. }    /* TestLock */
  243.